package com.dhecp.common.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Time;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;

/** 
* @ClassName: TypeUtil 
* @Description: JAVA类型转换工具类
* @author Administrator
* @date 2015年12月19日 
*/
public class TypeUtils {
	public static Boolean tryParseInt(String source) {
		if (StringUtils.isEmpty(source)) {
			return false;
		}
		try {
			Integer.parseInt(source);
			return true;
		} catch (NumberFormatException e) {
		}
		return false;
	}

	public static int getSafeInt(String source, int defaultInt) {
		source = StringUtils.isEmpty(source) ? "" : source;
		return tryParseInt(source) ? Integer.parseInt(source) : defaultInt;
	}

	public static Boolean tryParseFloat(String source) {
		if (StringUtils.isEmpty(source)) {
			return false;
		}
		try {
			Float.parseFloat(source);
			return true;
		} catch (NumberFormatException e) {
		}
		return false;
	}

	public static Float getSafeFloat(String source, Float defaultFloat) {
		source = StringUtils.isEmpty(source) ? "" : source;
		return tryParseFloat(source) ? Float.parseFloat(source) : defaultFloat;
	}

	public static Boolean tryParseDouble(String source) {
		if (StringUtils.isEmpty(source)) {
			return false;
		}
		try {
			Double.parseDouble(source);
			return true;
		} catch (NumberFormatException e) {
		}
		return false;
	}

	public static Double getSafeDouble(String source, Double defaultDouble) {
		source = StringUtils.isEmpty(source) ? "" : source;
		return tryParseDouble(source) ? Double.parseDouble(source) : defaultDouble;
	}

	public static Boolean tryParseLong(String source) {
		if (StringUtils.isEmpty(source)) {
			return false;
		}
		try {
			Long.parseLong(source);
			return true;
		} catch (NumberFormatException e) {
		}
		return false;
	}

	public static Long getSafeLong(String source, Long defaultLong) {
		source = StringUtils.isEmpty(source) ? "" : source;
		return tryParseLong(source) ? Long.parseLong(source) : defaultLong;
	}

	public static Boolean tryParseDate(String source) {
		if (StringUtils.isEmpty(source)) {
			return false;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		ParsePosition pos = new ParsePosition(0);
		try {
			dateFormat.setLenient(false);
			Date date = dateFormat.parse(source, pos);
			if (date == null) {
				return false;
			}
			if (pos.getIndex() > dateFormat.format(date).length()) {
				return false;
			}
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public static Date getSafeDate(String source, Date defaultDate) {
		if (tryParseDate(source)) {
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
			try {
				return dateFormat.parse(source);
			} catch (ParseException e) {
				return defaultDate;
			}
		}
		return defaultDate;
	}

	public static Boolean tryParseDateTime(String source) {
		if (StringUtils.isEmpty(source)) {
			return false;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		ParsePosition pos = new ParsePosition(0);
		try {
			dateFormat.setLenient(false);
			Date date = dateFormat.parse(source, pos);
			if (date == null) {
				return false;
			}
			if (pos.getIndex() > dateFormat.format(date).length()) {
				return false;
			}
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public static Date getSafeDateTime(String source, Date defaultDate) {
		if (tryParseDateTime(source)) {
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			try {
				return dateFormat.parse(source);
			} catch (ParseException e) {
				return defaultDate;
			}
		}
		return defaultDate;
	}

	public static Boolean tryParseBool(String source) {
		if (StringUtils.isEmpty(source)) {
			return false;
		}
		try {
			Boolean.parseBoolean(source);
			return true;
		} catch (NumberFormatException e) {
		}
		return false;
	}

	public static boolean getSafeBool(String source, Boolean defaultBool) {
		source = StringUtils.isEmpty(source) ? "" : source;
		return tryParseBool(source) ? Boolean.parseBoolean(source) : defaultBool;
	}

	// 获取指定格式化的日期 字符串(yyyy-MM-dd HH:mm:ss)
	public static String getStrDateTime(String datetime, String format) {
		if (StringUtils.isEmpty(datetime)) {
			return "";
		}
		if (StringUtils.isEmpty(format)) {
			format = "yyyy-MM-dd HH:mm:ss";
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat(format);
		try {
			Date dateObj = dateFormat.parse(datetime);
			return dateFormat.format(dateObj);
		} catch (ParseException e) {
			return "";
		}
	}

	// 获取指定格式化的时间 字符串（HH:mm:ss）
	public static String getStrTime(String datetime, String format) {
		if (StringUtils.isEmpty(datetime)) {
			return "";
		}
		if (StringUtils.isEmpty(format)) {
			format = "HH:mm:ss";
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		SimpleDateFormat timeFormat = new SimpleDateFormat(format);
		try {
			Date dateObj = dateFormat.parse(datetime);
			Time time = new Time(dateObj.getTime());
			return timeFormat.format(time);
		} catch (ParseException e) {
			return "";
		}
	}
	//格式化两位小数点
	public static String formatBigDecimal2Point(BigDecimal inValue){
		//DecimalFormat df = new DecimalFormat("#.00");
		//String decimalStr = df.format(inValue);
		//return decimalStr;
		return inValue.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
	}
	//格式化两位小数点
	public static String formatDouble2Point(double inValue){
//		DecimalFormat df = new DecimalFormat("#.00");
//		String decimalStr = df.format(inValue);
//		return decimalStr;
		BigDecimal b = new BigDecimal(inValue);
		return formatBigDecimal2Point(b);
	}
	
	/**
	 * 枚举类型转为Map格式
	 * @param enumT
	 * @return
	 * @author DH-Xxj
	 */
	public static <T> Map<String, Object> EnumToMap(Class<T> enumT,String... methodNames) {
		Map<String, Object> enummap = new LinkedHashMap<String, Object>();
		if (!enumT.isEnum()) {
			return enummap;
		}
		T[] enums = enumT.getEnumConstants();
		if (enums == null || enums.length <= 0) {
			return enummap;
		}
		int count = methodNames.length;
		String getCodeMathod = "getCode"; //默认获取Code方法
		String getInfoMathod = "getInfo";//默认获取Info方法
		if (count >= 1 && !"".equals(methodNames[0])) { //扩展方法
			getCodeMathod = methodNames[0];
		}
		if (count == 2 && !"".equals(methodNames[1])) {
			getInfoMathod = methodNames[1];
		}
		for (int i = 0, len = enums.length; i < len; i++) {
			T tobj = enums[i];
			try {
				Object resultCode = getMethodValue(getCodeMathod, tobj); //获取Code值
				if ("".equals(resultCode)) {
					continue;
				}
				Object resultInfo = getMethodValue(getInfoMathod, tobj); //获取Info描述值
				if ("".equals(resultInfo)) { //如果描述不存在获取属性值
					resultInfo = tobj;
				}
				enummap.put(resultCode.toString(), resultInfo);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return enummap;
	}

	/**
	 * 枚举类型转为List格式
	 * @param enumT
	 * @return
	 * @author DH-Xxj
	 */
	public static <T> List<Map<String,Object>> EnumToList(Class<T> enumT, String... methodNames) {
		List<Map<String,Object>> enumlist =  new ArrayList<>();
		if (!enumT.isEnum()) {
			return enumlist;
		}
		T[] enums = enumT.getEnumConstants();
		if (enums == null || enums.length <= 0) {
			return enumlist;
		}
		int count = methodNames.length;
		String getCodeMathod = "getCode"; //默认获取Code方法
		String getTagMathod = "getTag"; //默认获取Code方法
		String getInfoMathod = "getInfo";//默认获取Info方法
		if (count >= 1 && !"".equals(methodNames[0])) { //扩展方法
			getCodeMathod = methodNames[0];
		}
		if (count >= 2 && !"".equals(methodNames[1])) { //扩展方法
			getTagMathod = methodNames[1];
		}
		if (count == 3 && !"".equals(methodNames[2])) {
			getInfoMathod = methodNames[2];
		}
		for (int i = 0, len = enums.length; i < len; i++) {
			T tobj = enums[i];
			try {
				Object resultCode = getMethodValue(getCodeMathod, tobj); //获取Code值
				if ("".equals(resultCode)) {
					continue;
				}
				Object resultTag = getMethodValue(getTagMathod, tobj); //获取Tag值
				if ("".equals(resultTag)) {
					continue;
				}
				Object resultInfo = getMethodValue(getInfoMathod, tobj); //获取Info描述值
				if ("".equals(resultInfo)) { //如果描述不存在获取属性值
					resultInfo = tobj;
				}
				Map<String, Object> enummap = new LinkedHashMap<String, Object>();
				enummap.put("Code", resultCode.toString());
				enummap.put("Tag", resultTag.toString());
				enummap.put("Info", resultInfo);
				enumlist.add(enummap);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return enumlist;
	}

	/**
	 * 根据反射，通过方法名称获取方法值，忽略大小写的
	 * @param methodName
	 * @param obj
	 * @param args
	 * @return return value
	 */
	private static <T> Object getMethodValue(String methodName, T obj,Object... args) {
		Object resut = "";
		try {
			Method[] methods = obj.getClass().getMethods(); //获取方法数组，这里只要共有的方法
			if (methods.length <= 0) {
				return resut;
			}
			Method method = null;
			for (int i = 0, len = methods.length; i < len; i++) {
				if (methods[i].getName().equalsIgnoreCase(methodName)) { //忽略大小写取方法
					methodName = methods[i].getName(); //如果存在，则取出正确的方法名称
					method = methods[i];
					break;
				}
			}
			if (method == null) {
				return resut;
			}
			resut = method.invoke(obj, args); //方法执行
			if (resut == null) {
				resut = "";
			}
			return resut; //返回结果
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resut;
	}

	/**
	 * 以Map形式返回实体所有属性
	 * @param params
	 * @return Map
	 * @author DH-Xxj
	 */
	public static Map<String, Object> entityFieldsToMap(Object params){
		Map<String, Object> returnMap = new HashMap<String, Object>();
		Class<?> entityClass = params.getClass().getSuperclass();
		for (; entityClass != Object.class; entityClass = entityClass.getSuperclass()) {//向上循环  遍历父类
			Field[] fields = entityClass.getDeclaredFields();
			for (Field field : fields) {
				try {
					field.setAccessible(true);
					String name = new String(field.getName());
					returnMap.put(name.toLowerCase(), name); 
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				}				
			}
		}
		//当前类
		Field[] fields = params.getClass().getDeclaredFields();	
		try{		
			for (Field field : fields) {
				field.setAccessible(true);
				String name = new String(field.getName());
				returnMap.put(name.toLowerCase(), name); 
		   }
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		}
		return returnMap;		
	}

	/**
	 * 实体类型转换为Map格式
	 * @param params
	 * @return Map
	 * @author DH-Xxj
	 */
	public static Map<String, Object> entityToMap(Object params){
		Map<String, Object> returnMap = new HashMap<String, Object>();
		Class<?> entityClass = params.getClass().getSuperclass();
		Class<?> typeClass = null;
		for (; entityClass != Object.class; entityClass = entityClass.getSuperclass()) {//向上循环  遍历父类
			Field[] fields = entityClass.getDeclaredFields();
			for (Field field : fields) {
				try {
					Object value = "";
					Object value2 = "";
					field.setAccessible(true);
					typeClass = field.getType();
					if(field.get(params) == null){
						value = "";
					}else if(typeClass == Date.class){
						SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						value = formatter.format(field.get(params));
						SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd");
						value2 = formatter2.format(field.get(params));
						if (value.toString().equals(value2 + " 00:00:00")){
							value = value2;
						}
					}else if(typeClass == Double.class){	//防止因数值过大（超过一千万）而转换成科学计数法
						value = new BigDecimal(field.get(params).toString()).toPlainString();
					}else{
						value = field.get(params);
					}
					String name = new String(field.getName());
					returnMap.put(name, value); 
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				
			}
		}
		//当前类
		Field[] fields = params.getClass().getDeclaredFields();	
		try{	
//			returnMap.put("code", "0");
//			returnMap.put("msg", "转换成功");	
			for (Field field : fields) {
				Object value = "";
				Object value2 = "";
				field.setAccessible(true);
				typeClass = field.getType();
				if(field.get(params) == null){
					value = "";
				}else if(typeClass == Date.class){
					SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					value = formatter.format(field.get(params));
					SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd");
					value2 = formatter2.format(field.get(params));
					if (value.toString().equals(value2 + " 00:00:00")){
						value = value2;
					}
				}else if(typeClass == Double.class){	//防止因数值过大（超过一千万）而转换成科学计数法
					value = new BigDecimal(field.get(params).toString()).toPlainString();
				}else{
					value = field.get(params);
				}
				String name = new String(field.getName());
				returnMap.put(name, value); 
		   }
		}catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return returnMap;		
	}
	
	/**
	 * Map类型转换为String
	 * @param params
	 * @return String
	 * @author DH-Xxj
	 */
	public static String mapToString(Map<String, Object> params){
		JSONArray jArray = new JSONArray();
		jArray.add(params);
		String mapString = jArray.toString();
		return mapString;
	}
	
	/**
	 * Map类型转换为JSON对象
	 * @param params
	 * @returnObject
	 * @author DH-Xxj
	 */
	public static Object mapToJson(Map<String, Object> params){
		Object jsonObject = JSONObject.toJSON(params);
		return jsonObject;		
	}
	
	/**
	 * Json格式字符串转为Map
	 * @param jsonStr 格式：{"key1":"value1","key2":"value2"}
	 * @return Map
	 * @author DH-Xxj
	 */
	@SuppressWarnings("unchecked")
	public static Map<String,Object> jsonToMap(String jsonStr){
		return JSONObject.parseObject(jsonStr,Map.class);
	}
}
